<template>
  <div id="taskInfoManagePage" style="margin-left: 15px">
    <!-- 面包屑导航区域 -->
    <el-breadcrumb
      separator-class="el-icon-arrow-right"
      style="padding: 12px 12px"
    >
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>任务管理</el-breadcrumb-item>
      <el-breadcrumb-item>任务列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片视图区域 -->
    <el-card
      shadow="hover"
      style="margin-bottom: 15px; min-height: 580px; margin-right: 15px"
    >
      <el-row :gutter="20" style="margin: 12px 0">
        <el-col :span="8">
          <!-- 搜索与添加区域 -->
          <el-input
            v-model="queryInfo.keyword"
            placeholder="请输入内容搜索"
            :prefix-icon="Search"
            class="w-50 m-2"
          >
            <template #append>
              <el-button :icon="Search" @click="handleSearch" />
            </template>
          </el-input>
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="showAddDialog">添加任务</el-button>
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="handleLaunchSelected"
            >启动所选</el-button
          >
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="enableSelectedTimers"
            >开启所选定时</el-button
          >
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="disableSelectedTimer"
            >关闭所选定时</el-button
          >
        </el-col>
      </el-row>
      <!-- 任务信息列表区域  -->
      <el-table
        :data="taskInfoList"
        v-loading="queryLoading"
        @selection-change="handleSelectionChange"
        border
        stripe
        table-layout="auto"
      >
        <el-table-column type="selection" width="25" />
        <el-table-column label="序号" type="index"></el-table-column>
        <el-table-column
          label="任务名称"
          prop="name"
          width="290"
        ></el-table-column>
        <el-table-column
          label="源数据源"
          prop="srcDatasource.nickname"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="目标数据源"
          prop="dstDatasource.nickname"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="源表名"
          prop="srcTableName"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="目标表名"
          prop="dstTableName"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="查询SQL"
          prop="selectSql"
          show-overflow-tooltip
        ></el-table-column>
        <!-- <el-table-column label="查询SQL" prop="selectSql" type="expand">
          <template #default="props">
            <p style="margin: 0 12px">查询SQL: {{ props.row.selectSql }}</p>
          </template>
        </el-table-column> -->
        <el-table-column label="Fetch Size" prop="fetchSize"></el-table-column>
        <el-table-column label="缓冲区大小" prop="bufferSize"></el-table-column>
        <el-table-column
          label="任务启动前拦截器"
          prop="launchInterceptor"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="读后拦截器"
          prop="afterReadInterceptor"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="写后拦截器"
          prop="afterWriteInterceptor"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="任务组"
          prop="taskGroupInfo.name"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column label="操作" width="180px">
          <template v-slot="scope">
            <div style="display: flex">
              <!-- <el-button
                size="small"
                type="primary"
                @click="handleLaunch(scope.$index, scope.row)"
                >启动</el-button
              >
              <el-button
                size="small"
                type="primary"
                v-if="scope.row.timerState === 0"
                @click="handleTimerEnable(scope.$index, scope.row)"
                >定时</el-button
              >
              <el-button
                size="small"
                type="danger"
                v-if="scope.row.timerState === 1"
                @click="handleTimerDisable(scope.$index, scope.row)"
                >关闭</el-button
              > -->
              <el-button
                size="small"
                @click="handleEdit(scope.$index, scope.row)"
                >编辑</el-button
              >
              <el-button
                size="small"
                type="danger"
                @click="handleDelete(scope.$index, scope.row)"
                >删除</el-button
              >
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!-- 页面区域 -->
      <el-pagination
        style="margin: 15px 0"
        :current-page="queryInfo.currentPage"
        :page-sizes="[10, 25, 50, 100]"
        :page-size="queryInfo.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      >
      </el-pagination>
    </el-card>

    <!-- 弹窗表单 -->
    <el-dialog v-model="addDialogFormVisible" title="添加任务信息">
      <el-form :model="taskInfoForm" v-loading="saveLoading" :inline="true">
        <el-form-item label="任务名称" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.name" autocomplete="true" />
        </el-form-item>

        <el-form-item label="源数据源" :label-width="formLabelWidth">
          <el-select
            v-model="taskInfoForm.srcDsId"
            filterable
            remote
            reserve-keyword
            placeholder="请输入数据源名称"
            :remote-method="searchDs"
            :loading="loadingDs"
          >
            <el-option
              v-for="ds in dsList"
              :key="ds.id"
              :label="ds.nickname"
              :value="ds.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="目标数据源" :label-width="formLabelWidth">
          <el-select
            v-model="taskInfoForm.dstDsId"
            filterable
            remote
            reserve-keyword
            placeholder="请输入数据源名称"
            :remote-method="searchDs"
            :loading="loadingDs"
          >
            <el-option
              v-for="ds in dsList"
              :key="ds.id"
              :label="ds.nickname"
              :value="ds.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="源表名" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.srcTableName" autocomplete="true" />
        </el-form-item>
        <el-form-item label="目标表名" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.dstTableName" autocomplete="true" />
        </el-form-item>
        <el-form-item label="查询sql" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.selectSql" autocomplete="true" />
        </el-form-item>
        <el-form-item label="Fetch Size" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.fetchSize" autocomplete="true" />
        </el-form-item>
        <el-form-item label="缓冲区大小" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.bufferSize" autocomplete="true" />
        </el-form-item>
        <el-form-item
          label="任务启动前拦截器SpringBean名称"
          :label-width="formLabelWidth"
        >
          <el-input
            v-model="taskInfoForm.launchInterceptor"
            autocomplete="true"
          />
        </el-form-item>
        <el-form-item
          label="读后拦截器SpringBean名称"
          :label-width="formLabelWidth"
        >
          <el-input
            v-model="taskInfoForm.afterReadInterceptor"
            autocomplete="true"
          />
        </el-form-item>
        <el-form-item
          label="写后拦截器SpringBean名称"
          :label-width="formLabelWidth"
        >
          <el-input
            v-model="taskInfoForm.afterWriteInterceptor"
            autocomplete="true"
          />
        </el-form-item>

        <el-form-item label="CRON表达式" :label-width="formLabelWidth">
          <el-input v-model="taskInfoForm.cronExpr" autocomplete="true" />
        </el-form-item>

        <el-form-item label="所属任务组" :label-width="formLabelWidth">
          <el-select
            v-model="taskInfoForm.groupId"
            value-key="taskInfoForm.taskGroupInfo.id"
            filterable
            remote
            reserve-keyword
            placeholder="请输入任务组名称"
            :remote-method="searchTaskGroup"
            :loading="loadingTaskGroup"
          >
            <el-option
              v-for="group in taskGroupList"
              :key="group.id"
              :label="group.name"
              :value="group.id"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="addDialogFormVisible = false">取消</el-button>
          <el-button type="primary" @click="handleAdd">保存</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Search } from "@element-plus/icons-vue";
import { to, httpPost, httpGet } from "@/repository/network/";
import { isEmpty } from "@/util/string-util";

const queryInfo = reactive({
  keyword: "", // 查询参数
  currentPage: 1, // 当前页码
  pageSize: 10, // 每页显示条数
});
const taskInfoList = ref([]);
// 总数据条数
const total = ref(0);

// 新建对话框表单是否显示
const addDialogFormVisible = ref(false);
const taskInfoForm = ref({});
const formLabelWidth = "200px";
const saveLoading = ref(false);
const queryLoading = ref(true);

// 搜索数据源相关
const dsList = ref(new Array<any>());
const loadingDs = ref(false);

// 搜索任务组相关
const taskGroupList = ref(new Array<any>());
const loadingTaskGroup = ref(false);

// 多选数据相关
const multiSelections = ref<any[]>([]);

async function searchDs(query: string) {
  loadingDs.value = true;
  console.log(query);
  if (!query) {
    return;
  }
  const { resp, error } = await to(
    httpGet("/admin/ds/search", { keyword: query })
  );
  loadingDs.value = false;
  if (resp?.code !== 200) {
    ElMessage.error("加载数据源失败");
    return;
  }
  dsList.value = resp?.data?.data;
}

const handleSelectionChange = (val: any[]) => {
  multiSelections.value = val;
};

async function searchTaskGroup(query: string) {
  loadingTaskGroup.value = true;
  console.log(query);
  if (!query) {
    return;
  }
  const { resp, error } = await to(
    httpGet("/admin/task-group-info/search", { keyword: query })
  );
  loadingTaskGroup.value = false;
  if (resp?.code !== 200) {
    ElMessage.error("加载任务组失败");
    return;
  }
  taskGroupList.value = resp?.data?.data;
}

onMounted(() => {
  getTaskInfoList();
});

function showAddDialog() {
  addDialogFormVisible.value = true;
}

function enableSelectedTimers() {
  ElMessageBox.confirm("立即开启所选任务的定时开关?", "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await handleenableSelectedTimers();
    })
    .catch(() => {});
}

async function handleenableSelectedTimers() {
  let taskIds = [];
  for (const it of multiSelections.value) {
    taskIds.push(it.id);
  }
  if (!taskIds) {
    ElMessage.warning("请勾选任务");
    return;
  }
  const { resp, error } = await to(
    httpPost("/admin/task-info/enableSelectedTimers", { taskIds })
  );
  if (resp?.code != 200) {
    ElMessage.error("关闭失败, " + resp?.msg);
    return;
  }
  ElMessage.success("关闭成功!");
}

function handleLaunch(index: number, row: any) {
  ElMessageBox.confirm("立即启动此任务?", "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "启动",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await launchTask(row?.id);
    })
    .catch(() => {});
}

async function launchTask(taskId: string) {
  const { resp, error } = await to(httpGet("/admin/task-info/run", { taskId }));
  if (resp?.code != 200) {
    ElMessage.error("启动失败, " + resp?.msg);
    return;
  }
  ElMessage.success("启动成功!");
}

function handleLaunchSelected() {
  ElMessageBox.confirm(`立即启动所选任务?`, "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "启动",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await launchSelectedTasks();
    })
    .catch(() => {});
}

async function launchSelectedTasks() {
  const selected = multiSelections.value;
  let taskIds = [];
  for (const it of selected) {
    taskIds.push(it.id);
  }
  if (!taskIds) {
    ElMessage.warning("请勾选任务");
    return;
  }
  const { resp, error } = await to(
    httpPost("/admin/task-info/runTasks", { taskIds })
  );
  if (resp?.code != 200) {
    ElMessage.error("启动失败, " + resp?.msg);
    return;
  }
  ElMessage.success("启动成功!");
}

function disableSelectedTimer() {
  ElMessageBox.confirm(`立即关闭所选任务的定时开关?`, "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await disableSelecetedTaskTimers();
    })
    .catch(() => {});
}

async function disableSelecetedTaskTimers() {
  // 拿到所选的任务id列表
  let taskIds = [];
  for (const it of multiSelections.value) {
    taskIds.push((it as any).id);
  }
  if (!taskIds) {
    ElMessage.warning("请勾选任务");
    return;
  }
  const { resp, error } = await to(
    httpPost("/admin/task-info/disableSpecificTimers", { taskIds })
  );
  if (resp?.code != 200) {
    ElMessage.error("关闭失败, " + resp?.msg);
    return;
  }
  ElMessage.success("关闭成功!");
}

function handleTimerEnable(index: number, row: any) {
  ElMessageBox.confirm("立即打开所选任务的定时开关?", "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await enableTimerTask(row?.id);
    })
    .catch(() => {});
}

function handleTimerDisable(index: number, row: any) {
  ElMessageBox.confirm("关闭定时任务?", "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "关闭",
    cancelButtonText: "取消",
    type: "info",
  })
    .then(async () => {
      await disableTimerTask(row?.id);
    })
    .catch(() => {});
}

async function enableTimerTask(taskId: string) {
  const { resp, error } = await to(
    httpGet("/admin/task-info/enableTimer", { taskId })
  );
  if (resp?.code != 200) {
    ElMessage.error("启动定时任务失败," + resp?.msg);
    return;
  }
  ElMessage.success("启动定时任务成功!");
  await getTaskInfoList();
}

async function disableTimerTask(taskId: string) {
  const { resp, error } = await to(
    httpGet("/admin/task-info/disableTimer", { taskId })
  );
  if (resp?.code != 200) {
    ElMessage.error("关闭失败," + resp?.msg);
    return;
  }
  ElMessage.success("关闭成功!");
  await getTaskInfoList();
}

async function handleAdd() {
  saveLoading.value = true;
  const { resp, error } = await to(
    httpPost("/admin/task-info/addOrUpdate", taskInfoForm.value)
  );
  saveLoading.value = false;
  if (resp?.code != 200) {
    ElMessage.error("保存失败, " + resp?.msg);
    return;
  }
  await getTaskInfoList();
  ElMessage.success("保存成功！");
  addDialogFormVisible.value = false;
  taskInfoForm.value = {};
}

async function getTaskInfoList() {
  queryLoading.value = true;
  const { resp, error } = await to(
    httpPost("/admin/task-info/paging", queryInfo)
  );
  queryLoading.value = false;
  if (resp?.code != 200) {
    ElMessage.error("加载任务信息列表时出错");
    return;
  }
  taskInfoList.value = resp?.data?.data?.records;
  total.value = resp?.data?.data?.total;

  initDsSelect();
  initTaskGroupSelect();
}

function initDsSelect() {
  // 写入dsList让源数据源和目标数据源的select框能正常回显数据源名称而不是显示数据源id
  dsList.value = [];
  let set = new Set();
  for (const taskInfoItem of taskInfoList.value) {
    if (!set.has((taskInfoItem as any).srcDatasource.id)) {
      dsList.value.push((taskInfoItem as any).srcDatasource);
      set.add((taskInfoItem as any).srcDatasource.id);
    }
    if (!set.has((taskInfoItem as any).dstDatasource.id)) {
      dsList.value.push((taskInfoItem as any).dstDatasource);
      set.add((taskInfoItem as any).dstDatasource.id);
    }
  }
}

function initTaskGroupSelect() {
  // 写入taskGroupList让所属任务组的select框能正常回显任务组名称而不是显示任务组id
  taskGroupList.value = [];
  let set = new Set();
  for (const taskInfoItem of taskInfoList.value) {
    if (!set.has((taskInfoItem as any).taskGroupInfo.id)) {
      taskGroupList.value.push((taskInfoItem as any).taskGroupInfo);
      set.add((taskInfoItem as any).taskGroupInfo.id);
    }
  }
}

async function handleSearch() {
  getTaskInfoList();
}
function handleEdit(index: number, row: any) {
  taskInfoForm.value = row;
  addDialogFormVisible.value = true;
}
function handleDelete(index: number, row: any) {
  ElMessageBox.confirm("将永久删除此项，确定删除?", "警告", {
    distinguishCancelAndClose: true,
    confirmButtonText: "删除",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      const deleteSuccess = await requestDelete(row?.id);
      if (deleteSuccess) {
        await getTaskInfoList();
        ElMessage({
          type: "success",
          message: "删除成功",
        });
      }
    })
    .catch(() => {
      ElMessage({
        type: "info",
        message: "已取消",
      });
    });
}

async function requestDelete(id?: string): Promise<boolean> {
  if (!id) {
    return false;
  }
  const { resp, error } = await to(httpGet("/admin/task-info/remove", { id }));
  return resp?.code == 200;
}

// 监听 page size 改变的事件
function handleSizeChange(newSize: number) {
  queryInfo.pageSize = newSize;
  getTaskInfoList();
}
// 监听 页码值 改变的事件
function handleCurrentChange(newPage: number) {
  queryInfo.currentPage = newPage;
  getTaskInfoList();
}
</script>

<style>
</style>